home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Interactive 7
/
PC World Interactive 7.iso
/
program
/
ctutor.exe
/
SOURCE
/
DATA.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-05-15
|
15KB
|
452 lines
/* DATA.C - Data initialize and calculate */
/* Copyright (c) 1994 Coronado Enterprises */
#include <ctype.h>
#include <string.h>
#include <math.h>
#include "vc.h"
#include "video.h"
extern struct vars allvars[];
extern char inline[];
extern int col;
extern int errcode, colerr;
extern char strngout[];
/******************************************************** initdata */
/* This function is used to initialize all of the variables to the */
/* starting values including their variable names. */
void initdata(struct vars *pnt)
{
int index;
for (index = 0 ; index < 6 ; ++index) {
(pnt+index)->varname[0] = 'A' + index;
(pnt+index)->varname[1] = 0;
(pnt+index)->outtype = 'F';
(pnt+index)->value = 0.0;
}
for (index = 6 ; index < 12 ; ++index) {
(pnt+index)->varname[0] = 'I' + index - 6;
(pnt+index)->varname[1] = 0;
(pnt+index)->outtype = 'D';
(pnt+index)->value = 0;
}
(pnt+4)->value = 2.718281828459045;
(pnt+5)->value = 3.141592653589793;
(pnt+11)->value = 16777215;
}
/******************************************************** getnames */
/* This function reads in a new list of variable names to be used */
/* in place of the names A to F. This is only as a convenience */
/* for the user, so he can use more meaningful names. */
void getnames(void)
{
char var, index;
char dummy[80];
col = 1; /* skip over and ignore the # sign */
do {
if (inline[col] == ' ')
col++; /* ignore all leading blanks */
else {
var = inline[col] - 'A';
if ((var >= 0) && (var <= 5)) { /* A through F */
col++;
if (inline[col] != '-') { /* should be a dash */
errchk(14);
errout();
return;
}
col++;
for (index = 0 ; index < 6 ; index++) {
if (isalpha(inline[col]) || isdigit(inline[col])) {
dummy[index] = inline[col];
dummy[index + 1] = 0;
col++;
}
}
if (index > 0) {
strcpy(allvars[var].varname, dummy);
strcpy(strngout, " "); /* this is for */
strngout[6 - strlen(dummy)] = 0; /* leading blanks */
strcat(strngout, dummy);
strngdis_val(var + 1, 1);
}
} else if ((var >= 8) && (var <= 13)) { /* I through N */
col++;
if (inline[col] != '-') { /* should be a dash */
errchk(14);
errout();
return;
}
col++;
if ((inline[col] == 'O') || (inline[col] == 'D') ||
(inline[col] == 'H') || (inline[col] == 'X')) {
var -= 2;
allvars[var].outtype = inline[col];
col++;
}
else {
errchk(15);
errout();
return;
}
}
else { /* unknown variable name */
errchk(3);
errout();
return;
}
}
} while (inline[col] && (errcode == 0));
}
/******************************************************** calcdata */
/* This is the function that actually does the work of deciding */
/* what calculations need to be done. The method used is */
/* described in detail below. */
/* Three variables and two operators are number1 */
/* stored as per the list. "op1" is always op1 */
/* a plus or minus, and op2 is always a number2 */
/* multiplication or divide. If a plus or op2 */
/* minus is found for op2, number1 and number3 */
/* number2 are combined according to op1 */
/* and the result becomes number1, the new op2 becomes op1, and */
/* number3 becomes number2. If op2 is either a multiplication */
/* or divide, number2 and number3 are combined according to op2 */
/* and the result is placed in number2. When a parentheses is */
/* found, a recursive call is made and the expression in the */
/* parentheses is evaluated. A bit of study will be very */
/* fruitful in understanding this operation. */
void calcdata(double *newval)
{
double number1, number2, number3, getnum();
char op1, op2, getop();
number1 = 0.0;
op1 = '+';
number2 = 0.0;
while (inline[col] == ' ')
col++; /* ignore blanks */
/* check for unary operator */
if ((inline[col] == '+') || (inline[col] == '-')) {
op1 = inline[col];
col++;
}
number2 = getnum(); /* (inline[col]== 0 ) = End of line */
/* (inline[col]=='$') = End of line */
if ((inline[col] == 0) || (inline[col] =='$')) {
calcdat(&number1, &op1, &number2);
*newval = number1;
return;
}
for ( ; ; ) {
op2 = getop();
col++;
/* check for end of line 0, ), or $ */
if (op2 == '$')
op2 = 0; /* force a $ to lool like eol */
if ((op2 == 0) || (op2 == ')')) {
col++;
calcdat(&number1, &op1, &number2);
*newval = number1;
return;
}
number3 = getnum();
if ((op2 == '*') || (op2 == '/')){
calcdat(&number2, &op2, &number3);
} else {
calcdat(&number1, &op1, &number2);
op1 = op2;
number2 = number3;
}
} /* end of infinite for loop */
}
/********************************************************* calcdat */
/* This function actually does the calculations described in the */
/* function above. */
void calcdat(double *number1, char *op1, double *number2)
{
switch (*op1) {
case '*' : *number1 = (*number1) * (*number2);
break;
case '/' : if (*number2 == 0.0) {
errchk(10);
break;
}
*number1 = (*number1) / (*number2);
break;
case '+' : *number1 = *number1 + *number2;
break;
case '-' : *number1 = *number1 - *number2;
break;
default : break;
}
return;
}
/********************************************************** getnum */
/* This is the workhorse of the program. It actually scans the */
/* data input field and converts the data into numbers which are */
/* in the internal format of the computer so the calculations can */
/* be done. */
double getnum(void)
{
int index, i, decpt;
double newval;
char name[7];
double sqrt(), exp(), log(), sin(), cos(), atan();
while (inline[col] == ' ')
col++; /* ignore blanks */
index = inline[col];
if (index == '(') {
col++;
calcdata(&newval); /* recursive call */
col--;
return(newval);
}
decpt = 0; /* search for a decimal point */
i = col;
index = inline[i];
while ((index >= '0') && (index <= '9')) {
i++;
index = inline[i];
if (index == '.')
decpt = 1;
}
index = inline[col];
if (((index > '0') && (index <= '9')) ||
((index == '0') && (decpt == 1)) ||
(index == '.')) { /* floating number */
newval = 0.0;
while ((index >= '0') && (index <= '9')) {
newval = 10.0 * newval + (index - '0');
col++;
index = inline[col];
}
if (index == '.') {
double constant = 0.1;
col++;
index = inline[col];
while ((index >= '0') && (index <= '9')) {
newval = newval + (index - '0') * constant;
constant *= 0.1;
col++;
index = inline[col];
}
}
return(newval);
} /* end of floating point number */
if (index == '0') { /* octal or hexadecimal */
col++;
index = inline[col];
if ((index == 'x') || (index == 'X')){ /* hexadecimal */
col++;
index = inline[col];
newval = 0.0;
while (((index >= '0') && (index <= '9')) ||
((index >= 'A') && (index <= 'F')) ||
((index >= 'a') && (index <= 'f'))) {
switch (index) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':i = index - '0';
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':i = index - 'A' + 10;
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':i = index - 'a' + 10;
break;
default :break;
}
newval = 16.0 * newval + i;
col++;
index = inline[col];
}
return(newval);
} /* end of hexadecimal 'if' */
else { /* octal */
newval = 0.0;
while ((index >= '0') && (index <= '7')) {
newval = 8.0 * newval + (index - '0');
col++;
index = inline[col];
}
return(newval);
} /* end of octal 'else' */
} /* end of octal or hexadecimal numbers */
/* find variable or function name */
if ((inline[col] >= 'A') && (inline[col] <= 'Z')) {
name[0] = inline[col++];
i = 1;
while ((((inline[col] >= 'A') && (inline[col] <= 'Z')) ||
((inline[col] >= '0') && (inline[col] <= '9'))) &&
(i <= 5)) { /* continue var or function name */
name[i++] = inline[col++];
}
name[i] = 0; /* name found */
if (inline[col] == '('){ /* function call */
col++;
if (strcmp(name, "ABS") == 0) {
calcdata(&newval);
if (newval < 0.0)
newval = -newval;
} else if (strcmp(name, "SQRT") == 0) {
calcdata(&newval);
if (newval < 0.0) {
errchk(5); /* Neg value for SQRT */
newval = 0.0;
} else
newval = sqrt(newval);
} else if (strcmp(name, "FACT") == 0) {
calcdata(&newval);
if (newval < 0.0) {
errchk(16); /* Neg value for FACT */
newval = 0.0;
}
else {
double count;
int howmany;
count = newval;
newval = 1.0;
for (howmany = (int)count ; howmany > 1 ; howmany--) {
count = howmany;
newval = newval * count;
}
}
} else if (strcmp(name, "EXP") == 0) {
calcdata(&newval);
newval = exp(newval);
} else if (strcmp(name, "LOG") == 0) {
calcdata(&newval);
if (newval < 0.0) {
errchk(7); /* Neg value for LOG */
newval = 0.0;
} else newval = log(newval);
} else if (strcmp(name, "SIN") == 0){
calcdata(&newval);
newval = sin(newval);
} else if (strcmp(name, "COS") == 0){
calcdata(&newval);
newval = cos(newval);
} else if (strcmp(name, "ATAN") == 0){
calcdata(&newval);
newval = atan(newval);
} else {
errchk(6); /* function not found */
newval = 0.0;
}
col--;
return(newval);
} /* end of function call */
else { /* variable name */
for (i = 0 ; i < 12 ; i++) {
if ((strcmp(name, allvars[i].varname)) == 0) {
newval = allvars[i].value;
return(newval);
}
}
errchk(3); /* variable not found */
newval = 0.0;
return(newval);
} /* end of variable call */
} /* end of variable or function call */
errchk(9);
return(0.0); /* invalid data found */
}
/*********************************************************** getop */
/* A call to this function expects to find an operator, end of */
/* line or a close parenthesis. */
char getop(void)
{
while (inline[col] == ' ')
col++; /* ignore blanks */
switch (inline[col]){
case '$':
case ')':
case 0 :
case '+':
case '-':
case '*':
case '/': break;
default : errchk(4); /* invalid operator */
}
return(inline[col]);
}
/********************************************************** errchk */
/* The error code is stored by this function and the cursor column */
/* is adjusted in an attempt to put the cursor near the error */
/* that caused the problem. */
void errchk(int err)
{
if(errcode) return; /* error already found */
else { /* only the first error is stored */
errcode = err; /* store the error number */
switch (err) {
case 2 :
case 4 :
case 8 :
case 9 :
case 10 :
case 11 :
case 12 : colerr = col;
break;
case 1 :
case 3 : colerr = col - 1;
break;
case 6 : colerr = col - 2;
break;
case 5 :
case 7 : colerr = col - 3;
break;
default : colerr = col;
}
}
}